package com.transmit.util;

import com.google.api.client.util.Maps;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class LogUtil {

    private static final Logger logger = LoggerFactory.getLogger(LogUtil.class);

    public static String toString(Object newEntity, Object oldEntity,
                                  Map<String, String> fieldMap) {

        String content = "";
        Map<String, String> mapNew = Maps.newHashMap();
        Map<String, String> mapOld = Maps.newHashMap();
        try {

            mapNew = getDeclaredFieldsInfo(newEntity, fieldMap);
            if (null != oldEntity)//修改，对比历史信息
                mapOld = getDeclaredFieldsInfo(oldEntity, fieldMap);

            if (null != mapNew && mapNew.size() > 0) {

                for (String key : mapNew.keySet()) {
                    if (StringUtils.isNotBlank(mapNew.get(key))) {

                        String value = mapNew.get(key).toString();
                        //有效值
                        if (!value.equals("null") && !value.equals("0")) {
                            String oldValue = "";
                            if (StringUtils.isNotBlank(mapOld.get(key))) {
                                oldValue = mapOld.get(key);
                            }
                            if (StringUtils.isNotBlank(oldValue))
                                if (oldValue.equals(value)) //值相同，不写入日志中
                                    continue;

                            content += key + ": " + value + "<br/>";
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        mapNew = null;
        mapOld = null;
        if (StringUtils.isNotBlank(content))
            return "<div class='feedbackContent'>" + content + "</div>";
        else
            return "";
    }

    /**
     * 获取类中的中文注解名+属性值
     */
    public static Map<String, String> getDeclaredFieldsInfo(Object instance,
                                                     Map<String, String> fieldMap) throws Exception {
        Map<String, String> map = new HashMap();
        Class<?> clazz = instance.getClass();
        Field[] fields = clazz.getDeclaredFields();
        boolean b = false;
        for (Field field : fields) {
            // 除过fieldMap中的属性，其他属性都获取
            if (!fieldMap.containsValue(field.getName())) {
                boolean annotationPresent = field.isAnnotationPresent(ApiModelProperty.class);
                if (annotationPresent) {
                    // 获取注解值
                    //@ApiModelProperty(value = "点号", name = "pointNo")
                    String value = field.getAnnotation(ApiModelProperty.class).value();//ApiModelProperty.value
//                    String name = field.getAnnotation(ApiModelProperty.class).name();//ApiModelProperty.name

                    //获取属性值，不为空才返回
                    if (null != field.get(instance)) {
                        String object = field.get(instance).toString();
                        if (StringUtils.isNotBlank(object))
                            map.put(value, object.toString());
                    }
                }
            }
        }
        return map;
    }

    /**
     * 对象比较器
     *
     * @param oldMap 原对象参数
     * @param newMap 现对象参数
     * @return 返回比较之后的结果
     */
    private static StringBuffer comparatorObject(
            Map<String, LogValue> oldMap, Map<String, LogValue> newMap) {
        StringBuffer sb = new StringBuffer();
        if (oldMap != null && !oldMap.isEmpty()) {
            Set<Map.Entry<String, LogValue>> comparSet = oldMap.entrySet();
            for (Map.Entry<String, LogValue> entry : comparSet) {
                LogValue newVo = newMap.get(entry.getKey());
                LogValue oldVo = entry.getValue();
                Object newValue = newVo.getValue();
                Object oldValue = oldVo.getValue();
                if (null == newValue) {
                    continue;
                }
                Class<?> type = newValue.getClass();
                String typeName = newValue.getClass().getName();
                if (newVo != null) {
                    if ("java.lang.String".equals(typeName)) {
                        String newStr = (String) newValue;
                        String oldStr = (String) oldValue;
                        if (!StringUtils.equals(newStr, oldStr)) {
                            sb.append(showMsg(newVo, newStr, oldStr));
                        }
                    } else if ("java.sql.Timestamp".equals(typeName)) {
                        DateFormat format = new SimpleDateFormat(StringUtils.isBlank(newVo.getFormat()) ? "yyyy-MM-dd HH:mm:ss" : newVo.getFormat());
                        java.sql.Timestamp newTime = (java.sql.Timestamp) newValue;
                        java.sql.Timestamp oldTime = (java.sql.Timestamp) oldValue;
                        String newTempTimeStr = "";
                        String oldTimeTimeStr = "";
                        if (newTime != null) {
                            newTempTimeStr = format.format(newTime);
                        }
                        if (oldTime != null) {
                            oldTimeTimeStr = format.format(oldTime);
                        }
                        if (!StringUtils.equals(newTempTimeStr, oldTimeTimeStr)) {
                            sb.append(showMsg(newVo, format.format(newTime), format.format(oldTime)));
                        }
                    } else if ("java.lang.Long".equals(typeName) || Long.TYPE == type) {
                        Long newLog = NumberUtils.createLong(NumberUtils.isNumber(newValue + "") ? newValue + "" : "0");
                        Long oldLog = NumberUtils.createLong(NumberUtils.isNumber(oldValue + "") ? oldValue + "" : "0");
                        if (newLog.compareTo(oldLog) != 0) {
                            sb.append(showMsg(newVo, newLog, oldLog));
                        }
                    } else if ("java.lang.Integer".equals(typeName) || Integer.TYPE == type) {
                        Integer newInt = NumberUtils.createInteger(NumberUtils.isNumber(newValue + "") ? newValue + "" : "0");
                        Integer oldInt = NumberUtils.createInteger(NumberUtils.isNumber(oldValue + "") ? oldValue + "" : "0");
                        if (newInt.compareTo(oldInt) != 0) {
                            sb.append(showMsg(newVo, newInt, oldInt));
                        }
                    } else if ("java.lang.Boolean".equals(typeName) || Boolean.TYPE == type) {
                        Boolean newbool = BooleanUtils.toBoolean(newValue + "") ? true : false;
                        Boolean oldbool = BooleanUtils.toBoolean(oldValue + "") ? true : false;
                        if (newbool != oldbool) {
                            sb.append(showMsg(newVo, newbool, oldbool));
                        }
                    } else if ("java.lang.Character".equals(typeName)
                            || Character.TYPE == type) {
                        // 预留
                    } else if ("java.lang.Byte".equals(typeName) || Byte.TYPE == type) {
                        //预留不处理
                    } else if ("java.lang.Short".equals(typeName) || Short.TYPE == type) {
                        //预留不处理 有需要在处理
                    } else if ("java.lang.Float".equals(typeName) || Float.TYPE == type) {
                        Float newFloat = NumberUtils.createFloat(NumberUtils.isNumber(newValue + "") ? newValue + "" : "0");
                        Float oldFloat = NumberUtils.createFloat(NumberUtils.isNumber(oldValue + "") ? oldValue + "" : "0");
                        if (newFloat.compareTo(oldFloat) != 0) {
                            sb.append(showMsg(newVo, newFloat, oldFloat));
                        }
                    } else if ("java.lang.Double".equals(typeName) || Double.TYPE == type) {
                        Double newDouble = NumberUtils.createDouble(NumberUtils.isNumber(newValue + "") ? newValue + "" : "0");
                        Double oldDouble = NumberUtils.createDouble(NumberUtils.isNumber(oldValue + "") ? oldValue + "" : "0");
                        if (newDouble.compareTo(oldDouble) != 0) {
                            sb.append(showMsg(newVo, newDouble, oldDouble));
                        }
                    } else if ("java.util.Date".equals(typeName)) {
                        DateFormat format = new SimpleDateFormat(StringUtils.isBlank(newVo.getFormat()) ? "yyyy-MM-dd" : newVo.getFormat());
                        java.util.Date newTime = (java.util.Date) newValue;
                        java.util.Date oldTime = (java.util.Date) oldValue;
                        String newTempTimeStr = "";
                        String oldTimeTimeStr = "";
                        if (newTime != null) {
                            newTempTimeStr = format.format(newTime);
                        }
                        if (oldTime != null) {
                            oldTimeTimeStr = format.format(oldTime);
                        }
                        if (!StringUtils.equals(newTempTimeStr, oldTimeTimeStr)) {
                            sb.append(showMsg(newVo, format.format(newTime), format.format(oldTime)));
                        }
                    }
                }
            }
        }
        return sb;
    }

    /**
     * 页面标记
     */
    private static String showMsg(LogValue newVo, Object newLog,
                                  Object oldLog) {
        return "[" + newVo.getName() + "]发生变化由原先的:" + oldLog + "改变为:" + newLog + "/r/n";
    }

    //操作日志
    public static void setLog(int code, String value, String message, HttpServletRequest request) {
        request.getSession().setAttribute("code", code);
        request.getSession().setAttribute("type", value);
        request.getSession().setAttribute("msg", message);
    }
}
